package com.example.service;

import com.example.data.entity.kg.KgEntity;
import com.example.data.entity.kg.KgRelation;
import com.example.data.mapper.KgEntityMapper;
import com.example.data.mapper.KgRelationMapper;
import com.example.data.mapper.TripleMapper;
import com.example.data.vo.Triple;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 三元组服务（合并接口与实现：直接包含业务逻辑，无需单独ServiceImpl）
 */
@Service // 标记为Spring服务，可被Controller注入
public class TripleService {
    private static final Logger log = LoggerFactory.getLogger(TripleService.class);

    // 注入已有的实体表Mapper、关系表Mapper
    @Resource
    private KgEntityMapper kgEntityMapper;
    @Resource
    private KgRelationMapper kgRelationMapper;
    // 注入三元组专用Mapper（用于关联查询完整三元组）
    @Resource
    private TripleMapper tripleMapper;

    /**
     * 1. 新增三元组（核心逻辑：先确保头/尾实体存在→再新增关系，事务保证原子性）
     * @param headEntity 头实体（需包含 entityName、entityType，其他属性可选）
     * @param relation 关系（需包含 relationType、confidence，source信息可选）
     * @param tailEntity 尾实体（需包含 entityName、entityType，其他属性可选）
     * @return 新增的三元组对应的关系ID（kg_relation.id）
     */
    @Transactional(rollbackFor = Exception.class) // 事务：实体和关系要么一起成功，要么一起回滚
    public Long addTriple(KgEntity headEntity, KgRelation relation, KgEntity tailEntity) {
        // ------------------- 步骤1：处理头实体（不存在则新增，存在则复用ID） -------------------
        Long headEntityId = saveOrGetEntityId(headEntity);
        // ------------------- 步骤2：处理尾实体（逻辑同上） -------------------
        Long tailEntityId = saveOrGetEntityId(tailEntity);
        // ------------------- 步骤3：检查关系是否重复（避免重复插入） -------------------
        KgRelation duplicateRelation = kgRelationMapper.selectDuplicate(
                headEntityId, tailEntityId, relation.getRelationType()
        );
        if (duplicateRelation != null) {
            log.warn("三元组已存在：头实体ID={}，尾实体ID={}，关系类型={}",
                    headEntityId, tailEntityId, relation.getRelationType());
            return duplicateRelation.getId(); // 返回已存在的关系ID
        }
        // ------------------- 步骤4：填充关系的必要属性，插入关系表 -------------------
        relation.setSubjectEntityId(headEntityId); // 关联头实体ID
        relation.setObjectEntityId(tailEntityId);  // 关联尾实体ID
        relation.setIsValid(1);                    // 标记为有效
        relation.setCreateTime(LocalDateTime.now());// 设置创建时间
        relation.setUpdateTime(LocalDateTime.now());// 设置更新时间
        // 批量插入（即使单条也用批量方法，复用已有逻辑）
        kgRelationMapper.batchInsert(List.of(relation));
        log.info("三元组新增成功：头实体={}，关系={}，尾实体={}",
                headEntity.getEntityName(), relation.getRelationType(), tailEntity.getEntityName());
        return relation.getId(); // 返回新增的关系ID（若用自增ID，需确保Mapper返回自增ID）
    }

    /**
     * 工具方法：保存实体（若不存在则新增，存在则查询并返回ID）
     * @param entity 待处理的实体
     * @return 实体ID（新增或已存在的ID）
     */
    private Long saveOrGetEntityId(KgEntity entity) {
        // 先按“名称+类型”查询实体（避免同类型下重复实体）
        KgEntity existingEntity = kgEntityMapper.selectByNameAndType(
                entity.getEntityName(), entity.getEntityType()
        );
        if (existingEntity != null) {
            return existingEntity.getId(); // 实体已存在，返回ID
        }
        // 实体不存在，填充必要属性后插入
        entity.setIsValid(1);                    // 标记为有效
        entity.setCreateTime(LocalDateTime.now());// 设置创建时间
        entity.setUpdateTime(LocalDateTime.now());// 设置更新时间
        // 插入实体表（依赖KgEntityMapper的insert方法，用INSERT IGNORE避免重复）
        kgEntityMapper.insert(entity);
        // 插入后重新查询，获取自增ID（若Mapper的insert方法不返回ID，需此步骤）
        KgEntity newEntity = kgEntityMapper.selectByNameAndType(
                entity.getEntityName(), entity.getEntityType()
        );
        if (newEntity == null) {
            throw new RuntimeException("实体插入失败：" + entity.getEntityName() + "（类型：" + entity.getEntityType() + "）");
        }
        log.info("实体新增成功：名称={}，类型={}，ID={}",
                entity.getEntityName(), entity.getEntityType(), newEntity.getId());
        return newEntity.getId();
    }

    /**
     * 2. 查询所有有效三元组（关联实体表和关系表，返回完整结构）
     * @return 完整三元组列表（TripleVO）
     */
    public List<Triple> getAllValidTriples() {
        List<Triple> triples = tripleMapper.selectAllValidTriples();
        log.info("查询到有效三元组总数：{}", triples.size());
        return triples;
    }

    /**
     * 3. 按头实体ID查询三元组（如：查询“秦始皇”的所有关系）
     * @param headEntityId 头实体ID（kg_entity.id）
     * @return 该头实体关联的所有三元组
     */
    public List<Triple> getTriplesByHeadEntityId(Long headEntityId) {
        if (headEntityId == null) {
            log.error("头实体ID不能为空");
            return List.of();
        }
        List<Triple> triples = tripleMapper.selectTriplesByHeadEntityId(headEntityId);
        log.info("头实体ID={}，查询到三元组数量：{}", headEntityId, triples.size());
        return triples;
    }

    /**
     * 4. 按关系类型查询三元组（如：查询所有“定都”关系的三元组）
     * @param relationType 关系类型（如“定都”“建立”）
     * @return 该关系类型对应的所有三元组
     */
    public List<Triple> getTriplesByRelationType(String relationType) {
        if (relationType == null || relationType.trim().isEmpty()) {
            log.error("关系类型不能为空");
            return List.of();
        }
        List<Triple> triples = tripleMapper.selectTriplesByRelationType(relationType);
        log.info("关系类型={}，查询到三元组数量：{}", relationType, triples.size());
        return triples;
    }

    /**
     * 5. 统计有效三元组总数（仅统计“关系有效+头/尾实体有效”的三元组）
     * @return 有效三元组数量
     */
    public Integer countValidTriples() {
        Integer count = tripleMapper.countValidTriples();
        log.info("有效三元组总数：{}", count == null ? 0 : count);
        return count == null ? 0 : count;
    }

    public Map<String, Object> buildGraphData(Long startEntityId, Integer depth) {
        Map<String, Object> graph = new HashMap<>();
        Set<KgEntity> nodes = new HashSet<>();
        Set<KgRelation> links = new HashSet<>();

        // 如果指定了起始实体，获取其相关的实体和关系
        if (startEntityId != null) {
            KgEntity startNode = kgEntityMapper.selectById(startEntityId);
            if (startNode != null) {
                nodes.add(startNode);
                // 获取该实体作为主体的关系
                List<KgRelation> outgoing = kgRelationMapper.selectBySubjectId(startEntityId);
                links.addAll(outgoing);
                // 添加关联的客体实体
                outgoing.forEach(rel -> nodes.add(kgEntityMapper.selectById(rel.getObjectEntityId())));
            }
        } else {
            // 未指定起始实体时，返回部分核心数据（避免数据量过大）
            List<KgRelation> topRelations = kgRelationMapper.selectByRelationType("相关");
            topRelations.forEach(rel -> {
                links.add(rel);
                nodes.add(kgEntityMapper.selectById(rel.getSubjectEntityId()));
                nodes.add(kgEntityMapper.selectById(rel.getObjectEntityId()));
            });
        }

        graph.put("nodes", nodes.stream().map(this::convertToNodeVO).collect(Collectors.toList()));
        graph.put("links", links.stream().map(this::convertToLinkVO).collect(Collectors.toList()));
        return graph;
    }

    // 转换实体为前端需要的格式
    private Map<String, Object> convertToNodeVO(KgEntity entity) {
        Map<String, Object> node = new HashMap<>();
        node.put("id", entity.getId());
        node.put("name", entity.getEntityName());
        node.put("type", entity.getEntityType());
        node.put("desc", entity.getEntityDesc());
        return node;
    }

    // 转换关系为前端需要的格式
    private Map<String, Object> convertToLinkVO(KgRelation relation) {
        Map<String, Object> link = new HashMap<>();
        link.put("source", relation.getSubjectEntityId());
        link.put("target", relation.getObjectEntityId());
        link.put("label", relation.getRelationType());
        link.put("confidence", relation.getConfidence());
        return link;
    }

    /**
     * 根据实体名称查询实体（支持模糊匹配）
     * @param entityName 实体名称关键词
     * @return 匹配的实体列表
     */
    public List<KgEntity> getEntitiesByName(String entityName) {
        if (entityName == null || entityName.trim().isEmpty()) {
            throw new IllegalArgumentException("实体名称不能为空");
        }
        // 调用mapper进行模糊查询，限制最多返回10条结果
        return kgEntityMapper.fuzzySelectByName(entityName.trim());
    }


//    /**
//     * 基础版智能问答：基于模板匹配解析问题，返回自然语言答案
//     * @param question 用户问题（如“秦始皇建立了什么？”“秦朝属于什么类型？”）
//     * @return 自然语言答案（如“秦始皇建立了秦朝”）
//     */
//    public String answerQuestion(String question) {
//        if (question == null || question.trim().isEmpty()) {
//            return "请输入有效的问题~";
//        }
//        String trimmedQuestion = question.trim();
//
//        // ------------------- 模板1：查询实体描述（“X是谁？”“X是什么？”） -------------------
//        Pattern descPattern = Pattern.compile("(.*?)是(谁|什么)\\？");
//        Matcher descMatcher = descPattern.matcher(trimmedQuestion);
//        if (descMatcher.find()) {
//            String entityName = descMatcher.group(1).trim();
//            KgEntity entity = kgEntityMapper.selectByNameAndType(entityName, null); // 不指定类型，模糊匹配
//            if (entity != null) {
//                return entity.getEntityDesc() != null ? entity.getEntityDesc() : entityName + "是" + entity.getEntityType() + "类型的实体";
//            } else {
//                return "暂未查询到“" + entityName + "”的相关信息~";
//            }
//        }
//
//        // ------------------- 模板2：查询实体类型（“X属于什么类型？”） -------------------
//        Pattern typePattern = Pattern.compile("(.*?)属于什么类型\\？");
//        Matcher typeMatcher = typePattern.matcher(trimmedQuestion);
//        if (typeMatcher.find()) {
//            String entityName = typeMatcher.group(1).trim();
//            KgEntity entity = kgEntityMapper.selectByNameAndType(entityName, null);
//            if (entity != null) {
//                return entityName + "属于“" + entity.getEntityType() + "”类型~";
//            } else {
//                return "暂未查询到“" + entityName + "”的类型信息~";
//            }
//        }
//
//        // ------------------- 模板3：查询指定关系的尾实体（“X建立了什么？”“X定都在哪里？”） -------------------
//        // 关系映射：问题关键词 → 知识图谱中的关系类型
//        String[][] relationMap = {
//                {"建立", "建立"},    // 问题中的“建立”对应关系表的“建立”
//                {"定都", "定都"},    // 问题中的“定都”对应关系表的“定都”
//                {"统治", "统治"},    // 可根据你的关系类型扩展
//                {"消灭", "消灭"}
//        };
//        for (String[] map : relationMap) {
//            String questionKeyword = map[0];
//            String kgRelationType = map[1];
//            // 匹配问题：“X+关系关键词+了什么？”“X+关系关键词+在哪里？”
//            Pattern relationPattern = Pattern.compile("(.*?)" + questionKeyword + "了?(什么|哪里)\\？");
//            Matcher relationMatcher = relationPattern.matcher(trimmedQuestion);
//            if (relationMatcher.find()) {
//                String headEntityName = relationMatcher.group(1).trim();
//                // 1. 先根据实体名称查实体ID
//                KgEntity headEntity = kgEntityMapper.selectByNameAndType(headEntityName, null);
//                if (headEntity == null) {
//                    return "暂未查询到“" + headEntityName + "”的相关信息~";
//                }
//                // 2. 查该实体+该关系对应的三元组
//                List<Triple> triples = tripleMapper.selectTriplesByHeadEntityIdAndRelationType(
//                        headEntity.getId(), kgRelationType
//                );
//                if (triples.isEmpty()) {
//                    return "暂未查询到“" + headEntityName + "”" + questionKeyword + "的相关实体~";
//                }
//                // 3. 生成答案（多个结果用“、”连接）
//                StringBuilder answer = new StringBuilder(headEntityName + questionKeyword + "了");
//                for (int i = 0; i < triples.size(); i++) {
//                    answer.append(triples.get(i).getTailEntityName());
//                    if (i < triples.size() - 1) {
//                        answer.append("、");
//                    }
//                }
//                answer.append("~");
//                return answer.toString();
//            }
//        }
//
//        // ------------------- 模板4：查询实体的所有关联关系（“哪些实体与X有关？”） -------------------
//        Pattern allRelationPattern = Pattern.compile("哪些实体与(.*?)有关\\？");
//        Matcher allRelationMatcher = allRelationPattern.matcher(trimmedQuestion);
//        if (allRelationMatcher.find()) {
//            String entityName = allRelationMatcher.group(1).trim();
//            KgEntity entity = kgEntityMapper.selectByNameAndType(entityName, null);
//            if (entity == null) {
//                return "暂未查询到“" + entityName + "”的相关信息~";
//            }
//            // 查该实体作为头实体的三元组
//            List<Triple> headTriples = tripleMapper.selectTriplesByHeadEntityId(entity.getId());
//            // 查该实体作为尾实体的三元组
//            List<Triple> tailTriples = tripleMapper.selectTriplesByTailEntityId(entity.getId());
//            if (headTriples.isEmpty() && tailTriples.isEmpty()) {
//                return "暂未查询到与“" + entityName + "”相关的实体~";
//            }
//            // 生成答案
//            StringBuilder answer = new StringBuilder("与“" + entityName + "”相关的实体有：");
//            // 处理头实体的关联（X-关系-Y）
//            for (Triple triple : headTriples) {
//                answer.append("通过“").append(triple.getRelationType()).append("”关联“").append(triple.getTailEntityName()).append("”，");
//            }
//            // 处理尾实体的关联（Y-关系-X）
//            for (Triple triple : tailTriples) {
//                answer.append("被“").append(triple.getHeadEntityName()).append("”通过“").append(triple.getRelationType()).append("”关联，");
//            }
//            // 去掉最后一个逗号
//            answer = new StringBuilder(answer.substring(0, answer.length() - 1)).append("~");
//            return answer.toString();
//        }
//
//        // ------------------- 未匹配到模板 -------------------
//        return "暂不支持该问题类型~ 目前可提问：\n1. X是谁？（如“秦始皇是谁？”）\n2. X属于什么类型？（如“秦朝属于什么类型？”）\n3. X建立了什么？（如“秦始皇建立了什么？”）\n4. 哪些实体与X有关？（如“哪些实体与秦始皇有关？”）";
//    }

    // ------------------- 新增TripleMapper方法：按头实体ID+关系类型查询三元组（需补充） -------------------
    // 注意：需要在TripleMapper接口和XML中新增对应的方法（见步骤3）


}